﻿using UnityEngine;
using System.Collections;

public class Character_Stab : MonoBehaviour {

	public float attackRange;
	//the range of the melee weapon.
	
	public int damage;
	//the damage that the attack deals.

	public float attackhitTime;
	//the amount of time it takes for the attack to land, from the beginning of the animation.
	
	public float force;
	//how much the attack pushes back the target.

	Character_Player character;

	bool attackBuffer;
	bool attackBufferAllowed;
	bool attackReady;
	
	float hitTimeCounter=-1f;
	
	Transform target;
	[HideInInspector]
	public bool lockActive;
	
	static int stabState = Animator.StringToHash("UpperBody.Stab"); 
	
	// Use this for initialization
	void Start () {
			character=GetComponent<Character_Player>();
		
		attackReady=true;
		attackBufferAllowed=true;
		
		attackRange*=transform.localScale.x;
		
	}
	
	void Update () {
		AnimatorStateInfo currentBaseState = character.anim.GetCurrentAnimatorStateInfo(0);
		if(character.attacking){
			if(currentBaseState.nameHash != stabState){
				lockActive=false;
				target=null;
				attackReady=true;
				attackBufferAllowed=true;
				
				if(attackBuffer==false){
					character.attacking=false;
				}
			}
		}

		if(attackBuffer&&attackReady){
			character.attacking=true;
			
			attackReady=false;
			attackBuffer=false;
			attackBufferAllowed=false;
			
			hitTimeCounter=attackhitTime;
			
			character.Knife.renderer.enabled = true;
			character.cc.TransmitStabSignal();
			
			TargetLock();	
		}
		
		if(hitTimeCounter>=0f){
			hitTimeCounter-=Time.deltaTime;
			
			if(hitTimeCounter<0f){
				hitTimeCounter=-1f;
				attackBufferAllowed=true;
				AttackHit ();
			}
		}
		
		if(lockActive){
			Vector3 destination=new Vector3(target.transform.position.x,0f,target.transform.position.z);
			character.dir=(destination-new Vector3(transform.position.x,0f,transform.position.z));
			float distTotal=character.dir.magnitude;
			character.dir/=distTotal;
			
			float rotAngle=GetAngle(		new Vector2(transform.position.x,transform.position.z),
												new Vector2(destination.x,destination.z));
			rotAngle=(-rotAngle+90f);
			character.rotTarget=Quaternion.Euler(new Vector3(0f,rotAngle,0f));
		}
	}

	float GetAngle(Vector2 startPos, Vector2 targetPos){
		float angle=(Mathf.Atan2((targetPos.y-startPos.y),(targetPos.x-startPos.x)))*(180f/Mathf.PI);
		return angle;
	}
	
	public void AttackStart(){
		if(attackBufferAllowed){
			attackBuffer=true;
		}
	}
	
	public void AttackCancel(){
		attackReady=true;
		attackBuffer=false;
		attackBufferAllowed=true;
		hitTimeCounter=-1f;
		lockActive=false;
		target=null;
	}
	
	void TargetLock(){
		target=null;
        GameObject[] targets = GameObject.FindGameObjectsWithTag("Player");
		
		float shortestDistance=Mathf.Infinity;
		
		if(targets.Length>0) {
			foreach (GameObject t in targets)  {
				if(t==this.gameObject) { continue; }
				Character_Player c=t.GetComponent<Character_Player>();
				
				if(c.invulnerable==false){
					float dist = Vector2.Distance(	new Vector2(transform.position.x,transform.position.z),
													new Vector2(t.transform.position.x,t.transform.position.z));
					
					if (dist<=(attackRange+(t.GetComponent<BoxCollider>().size.x*t.transform.localScale.x))&&dist<shortestDistance) { 
						target=t.transform;
						shortestDistance=dist;
					}
				}
			}
		}
		
		if(target){
			lockActive=true;
		}
	}
	
	public void AttackHit(){
		if(lockActive==false){
			TargetLock();	
		}
		
		if(lockActive){
			float dist = Vector2.Distance(	new Vector2(transform.position.x,transform.position.z),
											new Vector2(target.transform.position.x,target.transform.position.z));
			
			if(dist<=(attackRange+(target.GetComponent<BoxCollider>().size.x*target.transform.localScale.x))){
				bool hitSuccess=target.GetComponent<Character_Health>().Damage(damage);
				
				if(hitSuccess){
					Character_Player targetCha=target.GetComponent<Character_Player>();
					
					Vector3 hitDir=(new Vector3(target.transform.position.x,0f,target.transform.position.z)-
									new Vector3(transform.position.x,0f,transform.position.z));
					float distTotal=hitDir.magnitude;
					hitDir/=distTotal;

					targetCha.cc.SetVelocityViaNetwork(targetCha.speed[0] + (hitDir*force));
				}
			}
		}
	}
	
	public IEnumerator HideKnife(float waitTime){
       yield return new WaitForSeconds(waitTime);
       character.Knife.renderer.enabled = false;
    }
}
